//
//  StageManager.m
//  CandyJump
//
//  Created by Bon Lam on 19/03/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "StageManager.h"

#import "BackgroundObject.h"
#import "Character.h"

#import	"BackgroundRes.h"
#import "ObjectRes.h"
#import "SpriteSheetRes.h"

#import "CCDirector.h"
#import "ccMacros.h" 
#import "CCSprite.h"
#import "CCSpriteBatchNode.h"
#import "cpBody.h"

//=====================================================================================================================
@implementation StageManager

@synthesize modelArray;
@synthesize backgroundModelArray;

static StageManager *sharedManager = nil;

#pragma mark -
#pragma mark Singleton Object Functions
//---------------------------------------------------------------------------------------------------------------------
- (id)init
{
	self = [super init];
	if (self == nil)  {return self;}
	
	modelArray = [[NSMutableArray alloc] init];
	backgroundModelArray = [[NSMutableArray alloc] init];
	delegate = nil;
	maxHeight = 0.0f;
	
	return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (void)dealloc
{
	[modelArray release]; modelArray = nil;
	[backgroundModelArray release]; backgroundModelArray = nil;
	
	[super dealloc];
}

//---------------------------------------------------------------------------------------------------------------------
+ (id)allocWithZone:(NSZone *)zone
{
    return [[self sharedManager] retain];
}

//---------------------------------------------------------------------------------------------------------------------
- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (id)retain 
{
    return self;
}

//---------------------------------------------------------------------------------------------------------------------
- (NSUInteger)retainCount
{
    return NSUIntegerMax;  //denotes an object that cannot be released
}

//---------------------------------------------------------------------------------------------------------------------
- (void)release
{
    //do nothing
}

//---------------------------------------------------------------------------------------------------------------------
- (id)autorelease
{
    return self;
}

#pragma mark Custom Functions
//---------------------------------------------------------------------------------------------------------------------
+ (StageManager *)sharedManager
{
	if (sharedManager == nil) {
        sharedManager = [[super allocWithZone:NULL] init];
    }
    return sharedManager;
}

//---------------------------------------------------------------------------------------------------------------------
- (void)setDelegate:(id)del
{
	delegate = del;
}

#pragma mark Objects
//---------------------------------------------------------------------------------------------------------------------
- (void)manageObjects
{
	if (delegate == nil) { return; }
	
	CGSize screenSize = [CCDirector sharedDirector].winSize;
	Character *character = [delegate character];
	cpBody* characterBody = [character physicsBody];
	
	if (character == nil) { return; }
	if (characterBody == nil) { return; }
	
	//	Remove Objects that are passed to the bottom (exclude the character)
	NSMutableArray *objectsTobeRemoved = [[NSMutableArray alloc] init];
	for (Model *model in modelArray) {
		if (model.sprite.position.y < 0 && [model isKindOfClass:[Character class]] == NO) {
			[model removeSpriteFromParent];
			[objectsTobeRemoved addObject:model];
		}
	}
	[modelArray removeObjectsInArray:objectsTobeRemoved];
	[objectsTobeRemoved release];
	objectsTobeRemoved = nil;
	
	//	Check height of the character, if not to a certain level, do nothing
	//	Else generate objects in the coming height
	if (characterBody->p.y > maxHeight - screenSize.height) {
	
		[self generateObjects];
	}
	
	//	Handle Background
	[self manageBackground];

	return;
}

//---------------------------------------------------------------------------------------------------------------------
- (NSArray*)generateObjects
{
	CGSize screenSize = [CCDirector sharedDirector].winSize;
	float originalMaxheight = maxHeight;
	float currentheight = [delegate currentheight];
	
	ObjectRes *objectRes = [ObjectRes sharedRes];
	for (int i=0; i<5; i++) {
		
		float posx = (CCRANDOM_0_1() * screenSize.width);
		float posy = ((CCRANDOM_0_1()) * screenSize.height)+originalMaxheight;
		
		Model *model = [[[objectRes objectListDictionary] objectForKey:@"platform_01_standard"] copy];
		model.sprite.position = CGPointMake(posx, posy);
		[model setRenderOffset:CGPointMake(0, -currentheight)];
		
		[modelArray addObject:model];
		[delegate addStageObject:model];
		
		maxHeight = (maxHeight >= posy) ? maxHeight : posy;
		
		[model release];
	}
	
	return nil;
}

#pragma mark Background
//---------------------------------------------------------------------------------------------------------------------
- (void)loadBackgroundWithName:(NSString*)backgroundName
{
	BackgroundRes *backgroundRes = [BackgroundRes sharedRes];
	[backgroundRes loadBackground:backgroundName];
	NSArray* backgroundArray = backgroundRes.backgroundModelArray;

	for (BackgroundObject* backgroundObject in backgroundArray) {
		
		BackgroundObject *cloneObject = [backgroundObject copy];
		cloneObject.sprite.position = CGPointMake(cloneObject.posx, cloneObject.posy);
		[delegate addStageObject:cloneObject];
		[backgroundModelArray addObject:cloneObject];
		
		for (int i=1; i<=cloneObject.repeat; i++) {
			BackgroundObject* repeatObject = [backgroundObject createWithRepeatOffset:(int)(i * cloneObject.repeatOffset)];
			[delegate addStageObject:repeatObject];
			[backgroundModelArray addObject:repeatObject];
			[repeatObject release];
		}
		
		[cloneObject release];
	}
}

//---------------------------------------------------------------------------------------------------------------------
- (void)manageBackground
{
	CGSize screenSize = [CCDirector sharedDirector].winSize;
	int currentheight = [delegate currentheight];
	
	//	scroll the background objects, also re-position them
	for (BackgroundObject *backgroundObject in backgroundModelArray) {
		
		//	Total scroll point to this object
		float totalScroll = currentheight*backgroundObject.scrollY;
		//	The remainder of the total scroll point divide the screen height, i.e. the scroll point on the screen
		float scrollOnScreen = (int) (totalScroll - screenSize.height*((int)totalScroll/(int)screenSize.height));
		//	Apply the scroll point on screen to the object position
		float objectY = backgroundObject.posy - scrollOnScreen;
		
		//	Bound it back to the original position
		if (backgroundObject.repeatOffset > 0 && backgroundObject.posy - objectY >= backgroundObject.scrollOffset) {
			objectY = backgroundObject.posy;//objectY % backgroundObject.repeatOffset;
		}
		
		backgroundObject.sprite.position = CGPointMake(backgroundObject.sprite.position.x, objectY);
	}
}

@end